﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using BlobTowerDefense.Managers;
using BlobTowerDefense.Game_Entities;
using System.Collections.Generic;
using BlobTowerDefense.Tools;

using Matrix = Microsoft.Xna.Framework.Matrix;

namespace BlobTowerDefense.Game_Entities
{
    /// <summary>
    /// Trida uchovavajici dulezita data o vezich
    /// </summary>
    public class Tower
    {        
        private int damage;               //sila strel veze
        private float speed;          //rychlost strel veze
        private float range;            //polomer dostrelu veze
        private int cost;               //cena veze
        public Vector3 position;        //pozice veze
        private TOWERSPECIAL special;

        public TOWERTYPE TowerType { get; set; }
        public Vector3 Scale { get; set; }
                
        public Model Model { get; set; }

        public bool Emphasize { get; set; }

        private BulletManager bulletManager;

        private float internalTime;
        private float intervalShoot;

        private const float addTime = 0.01f;

        /// <summary>
        /// Konstruktor tridy Tower
        /// </summary>
        /// <param name="damage">Sila strel veze</param>
        /// <param name="speed">Rychlost strileni veze</param>
        /// <param name="range">Polomer dosahu strel veze</param>
        /// <param name="cost">Cena za vez</param>
        /// <param name="upgradeCost"></param>
        public Tower( Vector3 position, Vector3 scale, 
                      int damage = 0, float speed = 0.0f, float range = 0.0f, int cost = 0, int upgradeCost = 0)
        {
            this.damage = damage;
            this.speed = speed;            
            this.range = range;
            this.cost = cost;
            this.position = position;
            this.Scale = scale;

            this.Model = GamePage.content.Load<Model>("Models/buildingPlace");
            this.TowerType = TOWERTYPE.buildingPlace;

            this.bulletManager = new BulletManager();

            this.internalTime = 0.0f;

        }

        public void Update(EnemyEntity enemy)
        {
            if (this.TowerType != TOWERTYPE.buildingPlace)
            {
                internalTime += addTime;
                bulletManager.UpdateBullets();

                if (internalTime >= intervalShoot)
                {
                    internalTime %= intervalShoot;
                    if (enemy != null)
                    {
                        if (IsEnemyInRange(enemy))
                        {
                            Shoot(enemy);
                        }
                    }
                }
                if (enemy != null)
                {
                    this.bulletManager.CheckEnemyShot(enemy);
                }
            }
        }

        public void Draw()
        {
            List<Vector3> defaultColor = null;
            int i = 0;

            if (!Emphasize && TowerType != TOWERTYPE.buildingPlace)
                defaultColor = TowerManager.defaultColor[TowerType];

            foreach (ModelMesh mesh in this.Model.Meshes)
            {
                foreach (BasicEffect currentEffect in mesh.Effects)
                {
                    currentEffect.Projection = Camera.ProjectionMatrix;
                    currentEffect.View = Camera.ViewMatrix;

                    if (TowerType != TOWERTYPE.buildingPlace)
                    {
                        currentEffect.World = Matrix.CreateTranslation(this.position) *
                                              Matrix.CreateScale(this.Scale);
                    }
                    else
                    {
                        currentEffect.World = Matrix.CreateTranslation(new Vector3(this.position.X, this.position.Y, this.position.Z - 1.9f)) *
                            Matrix.CreateScale(this.Scale);
                    }

                    currentEffect.EnableDefaultLighting();
                    if (this.Emphasize)
                    {
                        currentEffect.DiffuseColor = Microsoft.Xna.Framework.Color.White.ToVector3();
                    }
                    else
                    {
                        if (TowerType != TOWERTYPE.buildingPlace)
                        {
                            currentEffect.DiffuseColor = defaultColor[i];
                        }
                    }

                    foreach (EffectPass pass in currentEffect.CurrentTechnique.Passes)
                    {
                        pass.Apply();
                        mesh.Draw();
                    }
                    i++;
                }
            }

            bulletManager.DrawBullets();
        }

        public void BuildTower(TowerStats stats)
        {
            if (stats.IsUpgraded)
            {
                this.cost = stats.Cost;
                this.damage = stats.UpgradedDamage;
                this.range = stats.UpgradedRange;
                this.speed = stats.UpgradedSpeed;
                this.intervalShoot = 1.0f / speed;
                this.TowerType = stats.TowerType;
                this.special = stats.Special;
                this.Model = GamePage.content.Load<Model>(stats.pathToModel);
            }
            else
            {
                this.cost = stats.Cost;
                this.damage = stats.Damage;
                this.range = stats.Range;
                this.speed = stats.Speed;
                this.intervalShoot = 1.0f / speed;
                this.TowerType = stats.TowerType;
                this.special = stats.Special;
                this.Model = GamePage.content.Load<Model>(stats.pathToModel);
            }
        }

        private bool IsEnemyInRange(EnemyEntity enemyEntity)
        {
            foreach (ModelMesh meshTower in this.Model.Meshes)
            {
                BoundingSphere boundingSphere_Tower = BoundingSphere_Tools.TransformBoundingSphere(meshTower.BoundingSphere, this.position, this.Scale.X, this.range);

                foreach (ModelMesh meshEnemy in enemyEntity.Model.Meshes)
                {
                    BoundingSphere boundingSphere_Enemy = BoundingSphere_Tools.TransformBoundingSphere(meshEnemy.BoundingSphere, enemyEntity.Position, enemyEntity.Scale);
                    
                    if(boundingSphere_Tower.Intersects(boundingSphere_Enemy))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        public void Shoot(EnemyEntity enemyEntity)
        {
            this.bulletManager.ShootBullet(this.position, enemyEntity.Position, this.special);
        }

        /// <summary>
        /// Metoda nastavi aktualni pozici ze souradnic x,y a z.
        /// </summary>
        /// <param name="x">X souradnice</param>
        /// <param name="y">Y souradnice</param>
        /// <param name="z">Z souradnice</param>
        public void setPosition(float x, float y, float z)
        {
            position.X = x;
            position.Y = y;
            position.Z = z;
        }

        public void Upgrade()
        {
            this.damage = TowerManager.DefaultTowerStats[this.TowerType].UpgradedDamage;
            this.range = TowerManager.DefaultTowerStats[this.TowerType].UpgradedRange;
            this.speed = TowerManager.DefaultTowerStats[this.TowerType].UpgradedSpeed;            
        }
    }
}
